package com.yswy.app.service.impl;


import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yswy.app.service.PayOrderService;
import com.yswy.app.service.PayOrderZfbLogService;
import com.yswy.app.service.SysConfigService;
import com.yswy.common.enums.PaymentStateEnums;
import com.yswy.common.utils.UserLockUtils;
import com.yswy.common.zfbOrder.ZfbKeyVo;
import com.yswy.domain.entity.AgreementOrder;
import com.yswy.domain.entity.PayOrderWxLog;
import com.yswy.domain.entity.PayOrderZfbLog;
import com.yswy.domain.entity.VipPrice;
import com.yswy.domain.mapper.PayOrderZfbLogMapper;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class PayOrderZfbLogServiceImpl extends ServiceImpl<PayOrderZfbLogMapper, PayOrderZfbLog> implements PayOrderZfbLogService {


    @Autowired
    private PayOrderService payOrderService;

    @Autowired
    private SysConfigService sysConfigService;

    @Override
    public PayOrderZfbLog generateOrder(String orderid ,
                                        String trademsg ,
                                        ZfbKeyVo zfbKeyVo,
                                        String callbackUrl,
                                        String uid,
                                        VipPrice vipPrice,
                                        String ip) {

        PayOrderZfbLog order = new PayOrderZfbLog();
        order.setOrderId(orderid);
        order.setTradeStr(trademsg);
        order.setAppId(zfbKeyVo.getAppId());
        order.setPrivateKey(zfbKeyVo.getJavaKey());
        order.setPublicKey(zfbKeyVo.getZfbKey());
        order.setSingType(zfbKeyVo.getSingType());
        order.setCertPath(zfbKeyVo.getCertPath());
        order.setPublicCertPath(zfbKeyVo.getPublicCertPath());
        order.setRootCertPath(zfbKeyVo.getRootCertPath());
        order.setChannelIp(ip);
        order.setCallbackUrl(callbackUrl);
        order.setState(PaymentStateEnums.NEW.getCode());
        order.setProductCode(zfbKeyVo.getProductCode());
        order.setUid(uid);
        order.setPayType(0);
        vipPrice.setUpdateTime(null);
        vipPrice.setCreateTime(null);
        order.setRechargeCount(vipPrice.getPrice());
        order.setItemInfo(JSONObject.fromObject(vipPrice).toString() );
        order.setCreateTime(new Date());

        save(order);
        return order;
    }



    @Override
    public PayOrderZfbLog generateAgreementOrder(String orderid ,
                                                 AlipayTradePayResponse response ,
                                                 ZfbKeyVo zfbKeyVo,
                                                 String callbackUrl,
                                                 String uid,Integer rechargeCount, AgreementOrder agreementOrder) {
        PayOrderZfbLog order = new PayOrderZfbLog();
        order.setOrderId(orderid);
        order.setAppId(zfbKeyVo.getAppId());
        order.setPrivateKey(zfbKeyVo.getJavaKey());
        order.setPublicKey(zfbKeyVo.getZfbKey());
        order.setSingType(zfbKeyVo.getSingType());
        order.setCertPath(zfbKeyVo.getCertPath());
        order.setPublicCertPath(zfbKeyVo.getPublicCertPath());
        order.setRootCertPath(zfbKeyVo.getRootCertPath());
        order.setCallbackUrl(callbackUrl);
        order.setProductCode(zfbKeyVo.getProductCode());
        order.setState(PaymentStateEnums.NEW.getCode());
        order.setUid(uid);
        order.setPayType(0);
        order.setRechargeCount(rechargeCount);
        order.setItemInfo(JSONObject.fromObject(agreementOrder).toString() );
        order.setCreateTime(new Date());
        order.setCallbackParameter(JSONObject.fromObject(response).toString());
        save(order);
        return order;
    }



    @Override
    public void callbackPayOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Thread.sleep(500);
        Date now = Calendar.getInstance().getTime();
        Map<String, String> parameters = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            parameters.put(key, valueStr);
        }
        log.info("支付宝parameters is [parameters={}]", parameters);
        String appid = request.getParameter("app_id");// appid
        String orderid = request.getParameter("out_trade_no");// 商户订单号
        String total_amount = request.getParameter("total_amount");//付款金额
        String alitradeno = request.getParameter("trade_no");//支付宝订单号
        String tradeStatus = request.getParameter("trade_status");// 交易状态
        String callbackParameterString = JSONArray.fromObject(parameters).toString();

        PayOrderZfbLog payOrderZfbLog = getOne(new LambdaQueryWrapper<PayOrderZfbLog>().eq(PayOrderZfbLog::getOrderId , orderid));
        if (null == payOrderZfbLog) {
            log.warn("支付宝订单号{}不存在", orderid);
            return;
        }
        payOrderZfbLog.setAlitradeno(alitradeno);
        payOrderZfbLog.setRefundTime(now);
        payOrderZfbLog.setCallbackParameter(callbackParameterString);


        //验签
        boolean signVerified = true ;
        if (payOrderZfbLog.getSingType() == 0 ){
            signVerified = AlipaySignature.rsaCheckV1(parameters, payOrderZfbLog.getPublicKey(), "utf-8", "RSA2");// 调用SDK验证签名
        }else if (payOrderZfbLog.getSingType() == 1){
            signVerified = AlipaySignature.rsaCertCheckV1(parameters, payOrderZfbLog.getPublicCertPath(), "utf-8", "RSA2");// 调用SDK验证签名
        }

        if (signVerified) {
            // 验证金额度
            int amount = getCentFromYuan(total_amount);
            int amountInDb = payOrderZfbLog.getRechargeCount();
            if (!sysConfigService.selectConfigByKey("sys.pay.isTest").equals("1")){
                if (amountInDb != amount) {
                    log.warn("支付宝订单号{}的支付金额{}与传入的金额{}不匹配", orderid, amountInDb, amount);
                    payOrderZfbLog.setState(PaymentStateEnums.TRADE_MONEY_FAIL.getCode());
                    payOrderZfbLog.setStateStr("TRADE_MONEY_FAIL");
                    return;
                }
            }


            log.info("支付回调，订单号{},交易状态{}", orderid, tradeStatus);
            Boolean isCallbackServcie = false ;
            switch (tradeStatus) {
                case "WAIT_BUYER_PAY":
                    log.info("支付宝支付回调-订单号{}等待支付", orderid);
                    payOrderZfbLog.setStateStr("WAIT_BUYER_PAY");
                    break;
                case "TRADE_CLOSED":
                    log.info("支付宝支付回调-订单号{}交易关闭", orderid);
                    payOrderZfbLog.setState(PaymentStateEnums.TRADE_CLOSED.getCode());
                    payOrderZfbLog.setStateStr("TRADE_CLOSED");
                    isCallbackServcie = true ;
                    break;
                case "TRADE_SUCCESS":
                    log.info("支付宝支付回调-订单号{}交易成功", orderid);
                    payOrderZfbLog.setState(PaymentStateEnums.TRADE_SUCCESS.getCode());
                    payOrderZfbLog.setStateStr("TRADE_SUCCESS");
                    isCallbackServcie = true ;
                    break;
                case "TRADE_FINISHED":
                    log.info("支付宝支付回调-订单号{}交易完成", orderid);
                    payOrderZfbLog.setState(PaymentStateEnums.TRADE_FINISHED.getCode());
                    payOrderZfbLog.setStateStr("TRADE_FINISHED");
                    isCallbackServcie = true ;
                    break;
                default:
                    log.warn("支付宝异步通知订单号{}失败,支付宝平台查询交易状态未知状态{}", orderid, tradeStatus);
            }
            //回调业务
            if (isCallbackServcie){
                callbackService(payOrderZfbLog);
            }

            updateById(payOrderZfbLog);
        } else {
            log.warn("支付宝异步通知订单号{}验签失败", orderid);
            payOrderZfbLog.setState(PaymentStateEnums.TRADE_FAIL.getCode());
            payOrderZfbLog.setStateStr("TRADE_FAIL");

        }
    }

    @Override
    public void callbackZfbYwPayOrder(String orderid) {
        PayOrderZfbLog payOrderZfbLog = getOne(new LambdaQueryWrapper<PayOrderZfbLog>().eq(PayOrderZfbLog::getOrderId , orderid));
        if (null == payOrderZfbLog) {
            log.warn("支付宝订单号{}不存在", orderid);
            return;
        }
        callbackService(payOrderZfbLog);
    }
    public void callbackService(PayOrderZfbLog payOrderZfbLog) {
        try {
            synchronized (UserLockUtils.getLock("orderid:"+payOrderZfbLog.getOrderId())){
                if (payOrderZfbLog.getPayType() == 0){//会员购买
                    payOrderService.callbackPayOrder(0 , payOrderZfbLog , null);
                }else {
                    log.warn("支付宝支付回调-订单号{}订单类型不存在", payOrderZfbLog.getOrderId());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("支付宝支付回调-订单号{}交易关闭,回调数据服失败", payOrderZfbLog.getOrderId());
        }
    }





    public int getCentFromYuan(String amountYuanStr) {
        BigDecimal amountYuan = new BigDecimal(amountYuanStr);
        BigDecimal unit = new BigDecimal(100);
        BigDecimal amountCent = amountYuan.multiply(unit);
        return amountCent.intValue();
    }

}
